﻿//************************************************************************************************
// 说明：点击文本框选择插入文本的插件
// 更新：2010年12月12日 14:31:34
//
// 使用：使用jquery选择器选中要使用该插件的对象，调用插件
//          如：  $("#tableId").careter(options);
//          或者：$("input").careter(options);
//
// 参数：JSON格式
//       == 普通参数 ==
//       data:       供选择的文本数组（必填！默认为null）,
//       horizontal: 是否水平布局（默认为false）,
//       title:      标题（默认为组件名称）,
//       showAnim:   显示方式（'default'（默认） \ 'show' \ 'slideDown' \ 'fadeIn'）
//       insertHtml: 是否允许插入html（默认为false）
//       closeMode:  关闭方式（json参数）
//                     |--- onBlur:    失去焦点时关闭（默认true）
//                     |--- onSelect:  点击插入项时关闭（默认false）
//                     |--- showClose: 显示关闭按钮（默认true）
//
//       == 回调函数 ==
//       onInsert(val)：插入文本前调用的方法
//                      val = 插入的文本内容
//                      返回 = 插入文本
//
// 作者：Serafin.Tiu
// 我的博客：http://www.youguanbumen.net
// 我的QQ：20109955
//*************************************************************************************************

$.fn.extend({
    careter: function (setting) {
        // 配置参数
        var configer = $.fn.extend({
            // 普通参数
            data: null,             // 数据源（字符串数组）
            horizontal: false,      // 是否水平布局
            title: 'Careter',       // 标题
            showAnim: 'default',    // 显示方式
            insertHtml: false,      // 是否允许插入html
            closeMode: {            // 关闭方式
                onBlur: true,       //   |--- 失去焦点时关闭
                onSelect: false,    //   |--- 点击插入项时关闭
                showClose: true     //   |--- 显示关闭按钮
            },
            selectOneTime: false,

            // 回调函数
            onInsert: null          // 插入文本前调用
        }, setting);


        if (configer.data == null) {
            return false;
        }

        // 对复杂参数进行修正
        configer.closeMode.onBlur = (configer.closeMode.onBlur == null || configer.closeMode.onBlur == true);
        configer.closeMode.onSelect = (configer.closeMode.onSelect != null && configer.closeMode.onSelect == true);
        configer.closeMode.showClose = (configer.closeMode.showClose == null || configer.closeMode.showClose == true);

        ////////////////////////////////////////////////////////////////////////////////////////////


        // 遍历选中的所有对象
        $(this).each(function () {
            //  获取当前的扩展对象，jquery对象
            var $extObj = $(this);

            // 获取当前的扩展对象，dom对象
            var thisObj = this;
            var tagName = thisObj.tagName.toUpperCase();
            if (tagName != "INPUT" && tagName != "TEXTAREA") {
                return;
            }


            // 创建背景块（最外层的块）
            var $careterBlock = $('<div class="Jquery-Careter border-radius" style="display:none"></div>')
                .data('extObj', $extObj)
                .css('position', 'absolute')
                .data('configer_showAnim', configer.showAnim)
                .data('configer_closeMode', configer.closeMode)
                .data('extObj', $extObj)
                .hover(function () {
                    // 移除扩展对象失去焦点事件的处理方法
                    $extObj.unbind('blur');
                },
                function () {
                    // 如果设置为失去焦点时不显示文本选择块，那么为扩展对象添加失去焦点的处理方法
                    if (configer.closeMode.onBlur) {
                        $extObj.blur(function () {
                            HideCareter($careterBlock);
                        });
                    }
                }).click(function (event) {
                    event.stopPropagation(); // 取消事件冒泡
                    HideCrarterWithBlur($careterBlock);
                });

            // 创建主块（包含标题和内容）
            var $careterBlockMain = $('<div class="Jquery-Careter-Main border-radius"></div>');


            // 创建标题块（包括标题和关闭按钮）
            var $careterBlockTitle = $('<div class="Jquery-Careter-Title border-radius-top"></div>');

            // 添加标题内容 到 标题快
            var $titleText = $('<span class="titleText">' + configer.title + '</span>')
                .appendTo($careterBlockTitle);

            // 如果需要显示关闭按钮，那么在标题栏添加一个关闭按钮
            if (configer.closeMode.showClose) {
                // 关闭按钮 到 标题快
                var $closeBtn = $('<span class="btnClose border-radius">关闭</span>')
                .appendTo($careterBlockTitle)
                .click(function () {
                    // 关闭按钮点击事件——隐藏主块
                    HideCareter($careterBlock);
                });
            }

            // 内容块
            var $careterBlockContent = $('<div class="Jquery-Careter-Content border-radius-bottom"></div>');

            // 内容列表
            var $itemList = $('<ul></ul>');
            for (var i = 0; i < configer.data.length; i++) {
                var dataVal = configer.data[i];
                var $item = $('<li class="border-radius">' + dataVal + '</li>').click(function () {
                    if (configer.closeMode.onSelect) {
                        HideCareter($careterBlock);
                    }

                    // 获取要插入的文本
                    var val = configer.insertHtml ? $(this).html() : $(this).text();
                    var insertContent = val;
                    // 插入文本
                    if (configer.onInsert != null) {
                        // 如果有设置回调函数，那么先执行回调函数
                        insertContent = configer.onInsert(val);
                    }
                    if (insertContent != null && insertContent != false && insertContent != '') {
                        insertAtCaret(thisObj, insertContent);
                    }
                });

                // 如果是水平布局，那么修改起显示方式
                if (configer.horizontal) {
                    $item.css('display', 'inline-block').css('float', 'left');
                }
                $item.appendTo($itemList);
            }

            // 添加html对象
            $itemList.appendTo($careterBlockContent);         // 把内容添加 到 内容快
            $careterBlockTitle.appendTo($careterBlockMain);   // 添加标题块 到 主块
            $careterBlockContent.appendTo($careterBlockMain); // 添加内容快 到 主块
            $careterBlockMain.appendTo($careterBlock);        // 添加主DIV块 到 背景块
            $careterBlock.appendTo($('body'));                // 把背景块添加 到 body

            // 为扩展对象添加事件处理方法
            $extObj.focus(function () {
                ShowCareter($careterBlock);
                HideCrarterWithBlur($careterBlock);
            });
            $extObj.click(function (event) {
                event.stopPropagation();  // 取消事件冒泡
                setCaret(thisObj);
            });
            $extObj.select(function () {
                setCaret(thisObj);
            });
            $extObj.keyup(function () {
                setCaret(thisObj);
            });
            if (configer.closeMode.onBlur) {
                $extObj.blur(function () {
                    HideCareter($careterBlock);
                });
            }

            $extObj.data('careter_configer', configer);
            $extObj.data('careter_configer', configer);

            // 为document增加点击事件
            $(document).click(function () {
                // 如果设置为失去焦点则关闭的话，那么关闭块
                if (configer.closeMode.onBlur) {
                    HideCareter($careterBlock);
                }
            });
        });


        ////////////////////////////////////////////////////////////////////////////////////////////

        //================================================
        // 说明：隐藏所有关闭模式设置为失去焦点时的块
        // 参数：$exceptCareterBlock = 除去这个块
        //------------------------------------------------
        function HideCrarterWithBlur($exceptCareterBlock) {
            if ($(document).data("activedCareterBlock") != null) {
                for (var i = 0; i < $(document).data("activedCareterBlock").length; i++) {
                    var block = $(document).data("activedCareterBlock")[i];
                    if (block.data('configer_closeMode').onBlur && block != $exceptCareterBlock) {
                        HideCareter(block);
                    }
                }
            }
        }

        //================================================
        // 说明：显示
        // 参数：$careterBlock = 要显示的块（背景块）
        //------------------------------------------------
        function ShowCareter($careterBlock) {

            // 设置要显示的位置
            $extObj = $careterBlock.data('extObj');
            var extDomOffset = $extObj.offset();
            var showLeft = extDomOffset.left;
            var showTop = extDomOffset.top + $extObj.outerHeight();
            $careterBlock.css('left', showLeft + "px");
            $careterBlock.css('top', showTop + "px");


            switch ($careterBlock.data('configer_showAnim')) {
                case 'show': $careterBlock.show('fast'); break;
                case 'slideDown': $careterBlock.slideDown('fast'); break;
                case 'fadeIn': $careterBlock.fadeIn('fast'); break;
                default: $careterBlock.show();
            }

            // 缓存当前活动的块
            if ($(document).data("activedCareterBlock") == null) {
                $(document).data("activedCareterBlock", new Array());
            }
            var exist = false;
            var loop = $(document).data("activedCareterBlock").length;
            for (var i = 0; i < loop; i++) {
                if ($(document).data("activedCareterBlock")[i] == $careterBlock) {
                    // 已经存在，那么不需要添加，跳出循环
                    exist = true;
                    break;
                }
            }
            if (!exist) {
                // 不存在，那么追加进去
                $(document).data("activedCareterBlock").push($careterBlock);
            }
        }

        //================================================
        // 说明：隐藏
        // 参数：$careterBlock = 要隐藏的块（背景块）
        //------------------------------------------------
        function HideCareter($careterBlock) {
            switch ($careterBlock.data('configer_showAnim')) {
                case 'show': $careterBlock.hide('fast'); break;
                case 'slideDown': $careterBlock.slideUp('fast'); break;
                case 'fadeIn': $careterBlock.fadeOut('fast'); break;
                default: $careterBlock.hide();
            }
        }

        //================================================
        // 说明：设置插入位置
        // 参数：textObj = 文本的插入对象（扩展DOM对象）
        //------------------------------------------------
        function setCaret(textObj) {
            if (textObj.createTextRange) {
                textObj.caretPos = document.selection.createRange().duplicate();
            }
        }

        //================================================
        // 说明：插入内容
        // 参数：textObj = 文本的插入对象（扩展DOM对象）
        //       textFeildValue =  插入的文本内容
        //------------------------------------------------
        function insertAtCaret(textObj, textFeildValue) {
            if (document.all) {
                if (textObj.createTextRange && textObj.caretPos) {
                    var caretPos = textObj.caretPos;
                    caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == '   ' ? textFeildValue + '   ' : textFeildValue;
                } else {
                    textObj.value = textFeildValue;
                }
            }
            else {
                if (textObj.setSelectionRange) {
                    var rangeStart = textObj.selectionStart;
                    var rangeEnd = textObj.selectionEnd;
                    var tempStr1 = textObj.value.substring(0, rangeStart);
                    var tempStr2 = textObj.value.substring(rangeEnd);
                    textObj.value = tempStr1 + textFeildValue + tempStr2;
                } else {
                    alert('您的浏览器不支持该插件哇 ^_^');
                }
            }
        }
    }
});
